﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Collections.ObjectModel;
using System.Collections;
using System.ComponentModel;
using Microsoft.Win32;
using System.Windows;
using System.Xml;
using DBDataAccessLib;
using DBDataAccessLib.DataMapping;
using System.Data;
using System.IO;
using System.Reflection;

namespace Infrastructure
{
    public static class Helper
    {
        public static string GetConfigurationValue(string key)
        {
            string value = ConfigurationManager.AppSettings[key];
            return value;
        }

        public static string BaseUri
        {
            get
            {
                return AppDomain.CurrentDomain.BaseDirectory;
            }
        }

        public static string ServerUrl
        {
            get { return GetConfigurationValue("ImageServerURI"); }
        }

        public static string ConnectionString
        {
            get
            {
                if (DBHelperFactory.DbName == DBType.SqlServer)
                    return ConfigurationManager.ConnectionStrings["SQLConnString1"].ConnectionString;//OraConnString1
                else return ConfigurationManager.ConnectionStrings["OraConnString1"].ConnectionString;//OraConnString1
            }
        }

        public static void UpdateNode(string xpath, string attributeName, string attributeValue)
        {
            XmlDocument doc = new XmlDocument();
            string exeName = AppDomain.CurrentDomain.FriendlyName.Split(".".ToCharArray())[0];
            string strFileName = AppDomain.CurrentDomain.BaseDirectory.ToString() + exeName + ".exe.config";
            doc.Load(strFileName);
            XmlNode node = doc.SelectSingleNode(xpath);
            if (node != null)
            {
                node.Attributes[attributeName].Value = attributeValue;
                doc.Save(strFileName);
            }
        }

        public static void UpdateAppSetting(string xpath, string attributeValue)
        {
            XmlDocument doc = new XmlDocument();
            string exeName = AppDomain.CurrentDomain.FriendlyName.Split(".".ToCharArray())[0];
            string strFileName = AppDomain.CurrentDomain.BaseDirectory.ToString() + exeName + ".exe.config";
            doc.Load(strFileName);
            XmlNode node = doc.SelectSingleNode(xpath);
            if (node != null)
            {
                node.Attributes["value"].Value = attributeValue;
                doc.Save(strFileName);
            }
        }

        public static string GetAppSetting(string key)
        {
            XmlDocument doc = new XmlDocument();
            string exeName = AppDomain.CurrentDomain.FriendlyName.Split(".".ToCharArray())[0];
            string strFileName = AppDomain.CurrentDomain.BaseDirectory.ToString() + exeName + ".exe.config";
            doc.Load(strFileName);
            XmlNode node = doc.SelectSingleNode("//appSettings/add[@key='" + key + "']");
            if (node != null) return node.Attributes["value"].Value;
            else return string.Empty;
        }

        public static string GetSqlConnection(string name)
        {
            XmlDocument doc = new XmlDocument();
            string strFileName = AppDomain.CurrentDomain.BaseDirectory.ToString() + "GuaranteePrintViewModel.exe.config";
            doc.Load(strFileName);
            XmlNode node = doc.SelectSingleNode("//connectionStrings/add[@name='" + name + "']");
            if (node != null) return node.Attributes["connectionString"].Value;
            else return string.Empty;
        }

        public static void ExportCSV(DataTable dataTable, string path)
        {
            StringBuilder sbData = new StringBuilder();

            foreach (DataColumn column in dataTable.Columns)
            {
                sbData.Append(column.ColumnName + ",");
            }
            sbData.AppendLine();

            foreach (DataRow row in dataTable.Rows)
            {
                foreach (DataColumn column in dataTable.Columns)
                {
                    sbData.Append(row[column].ToString() + ",");
                }
                sbData.AppendLine();
            }
            sbData.AppendLine();

            using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                byte[] buffer = System.Text.Encoding.GetEncoding(ConfigurationManager.AppSettings["CSVEncoding"]).GetBytes(sbData.ToString());
                fs.Write(buffer, 0, buffer.Length);
            }
        }

        public static DataTable ToDataTable<T>(this IEnumerable<T> list)
        {
            //创建属性的集合
            List<PropertyInfo> pList = new List<PropertyInfo>();
            //获得反射的入口
            Type type = typeof(T);
            DataTable dt = new DataTable();
            //把所有的public属性加入到集合 并添加DataTable的列
            Array.ForEach<PropertyInfo>(type.GetProperties(), p => { pList.Add(p); dt.Columns.Add(p.Name, p.PropertyType); });
            foreach (var item in list)
            {
                //创建一个DataRow实例
                DataRow row = dt.NewRow();
                //给row 赋值
                pList.ForEach(p => row[p.Name] = p.GetValue(item, null));
                //加入到DataTable
                dt.Rows.Add(row);
            }
            return dt;
        }
    }

    public static class WCNOMapping
    {
        static WCNOMapping()
        {
            WCNOS = new Dictionary<string, string>();
        }
        public static Dictionary<string, string> WCNOS { get; set; }
    }

    public static class SebangoMapping
    {
        static SebangoMapping()
        {
            Sebangos = new List<Pair<string, string>>();
        }

        public static List<Pair<string, string>> Sebangos { get; set; }
    }

    public static class CollectionHelper
    {
        public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> enumerableList)
        {
            if (enumerableList != null)
            {
                //create an emtpy observable collection object  
                var observableCollection = new ObservableCollection<T>();
                //loop through all the records and add to observable collection object  
                foreach (var item in enumerableList) observableCollection.Add(item);
                //return the populated observable collection  
                return observableCollection;
            }

            return null;

        }

        public static void AddRange<T>(this IEnumerable<T> enumerableList, IEnumerable<T> list)
        {
            if (enumerableList != null)
            {
                foreach (var item in list) enumerableList.Add(item);
            }
        }

        public static void Insert(this IEnumerable collection, int index, object item)
        {
            ICollectionView collectionView = collection as ICollectionView;
            if (collectionView != null)
            {
                Insert(collectionView.SourceCollection, index, item);
            }
            else
            {
                Type genericListType = collection.GetType().GetInterfaces().Where(
                    interfaceType => interfaceType.FullName.StartsWith("System.Collections.Generic.IList`1", StringComparison.Ordinal)
                    ).FirstOrDefault();

                if (genericListType != null)
                {
                    genericListType.GetMethod("Insert").Invoke(collection, new object[] { index, item });
                }
                else if (collection is IList)
                {
                    IList list = (IList)collection;

                    if (list != null)
                    {
                        list.Insert(index, item);
                    }
                }
                else
                {
                    throw new NotSupportedException();
                }
            }
        }

        public static int Count(this IEnumerable collection)
        {
            ICollectionView collectionView = collection as ICollectionView;
            if (collectionView != null)
            {
                return collectionView.SourceCollection.Count();
            }
            else
            {
                Type genericListType = collection.GetType().GetInterfaces().Where(interfaceType => interfaceType.FullName.StartsWith("System.Collections.Generic.ICollection`1", StringComparison.Ordinal)).FirstOrDefault();
                if (genericListType != null)
                {
                    return (int)genericListType.GetProperty("Count").GetValue(collection, new object[] { });
                }

                IList list = collection as IList;
                if (list != null)
                {
                    return list.Count;
                }

                return System.Linq.Enumerable.Count(collection.OfType<object>());
            }
        }

        public static void Add(this IEnumerable collection, object item)
        {
            ICollectionView collectionView = collection as ICollectionView;
            if (collectionView != null)
            {
                Add(collectionView.SourceCollection, item);
            }
            else
            {
                var count = collection.Count();

                Insert(collection, count, item);
            }
        }

        public static void Remove(this IEnumerable collection, object item)
        {
            ICollectionView collectionView = collection as ICollectionView;
            if (collectionView != null)
            {
                collectionView.SourceCollection.Remove(item);
            }
            else
            {
                Type genericListType = collection.GetType().GetInterfaces().Where(interfaceType => interfaceType.FullName.StartsWith("System.Collections.Generic.IList`1", StringComparison.Ordinal)).FirstOrDefault();
                if (genericListType != null)
                {
                    int index = (int)genericListType.GetMethod("IndexOf").Invoke(collection, new object[] { item });
                    if (index != -1)
                    {
                        genericListType.GetMethod("RemoveAt").Invoke(collection, new object[] { index });
                    }
                }
                else
                {
                    IList list = collection as IList;

                    if (list != null)
                    {
                        list.Remove(item);
                    }
                }
            }
        }

        public static void RemoveAt(this IEnumerable collection, int index)
        {
            ICollectionView collectionView = collection as ICollectionView;
            if (collectionView != null)
            {
                collectionView.SourceCollection.RemoveAt(index);
            }
            else
            {
                Type genericListType = collection.GetType().GetInterfaces().Where(interfaceType => interfaceType.FullName.StartsWith("System.Collections.Generic.IList`1", StringComparison.Ordinal)).FirstOrDefault();
                if (genericListType != null)
                {
                    genericListType.GetMethod("RemoveAt").Invoke(collection, new object[] { index });
                }
                else
                {
                    IList list = collection as IList;
                    list.RemoveAt(index);
                }
            }
        }

        public static ObservableCollection<T> RemoveRange<T>(this ObservableCollection<T> collection, IEnumerable<T> items)
        {
            if (items != null)
            {

                int i = items.ToListCollection().Count;

                while (i > 0)
                {
                    foreach (var item in items)
                    {
                        collection.Remove(item);
                        items.ToListCollection().Remove(item);
                        break;
                    }
                    i--;
                }
            }

            return collection;
        }

        public static List<T> RemoveRangeList<T>(this List<T> collection, IEnumerable<T> items)
        {
            if (items != null)
            {
                int i = items.ToListCollection().Count;
                while (i > 0)
                {
                    foreach (var item in items)
                    {
                        collection.Remove(item);
                        i--;
                        break;
                    }
                }
            }

            return collection;
        }


        public static List<T> ToListCollection<T>(this IEnumerable<T> coll)
        {
            var c = new List<T>();
            foreach (var e in coll)
                c.Add(e);
            return c;
        }

        public static ObservableCollection<T> Delete<T>(this ObservableCollection<T> coll)
        {
            var c = new ObservableCollection<T>();

            if (coll != null)
            {
                coll.Clear();
            }

            return c;
        }

        public static List<T> Delete<T>(this List<T> coll)
        {
            var c = new List<T>();

            if (coll != null)
            {
                coll.Clear();
            }

            return c;
        }

        public static IEnumerable<T> Distinct<T>(this IEnumerable<T> list, Func<T, object> keyExtractor)
        {
            return list.Distinct(new KeyEqualityComparer<T>(keyExtractor));
        }

        public static bool Contains<T>(this IEnumerable<T> list, T item, Func<T, object> keyExtractor)
        {
            return list.Contains(item, new KeyEqualityComparer<T>(keyExtractor));
        }

        public static bool Contains<T>(this IEnumerable<T> list, T item, Func<T, T, bool> keyExtractor)
        {
            return list.Contains(item, new KeyEqualityComparer<T>(keyExtractor));
        }

        public static IEnumerable<T> Except<T>(this IEnumerable<T> list, IEnumerable<T> except, Func<T, object> keyExtractor)
        {
            return list.Except(except, new KeyEqualityComparer<T>(keyExtractor));
        }

        public static IEnumerable<T> Intersect<T>(this IEnumerable<T> list, IEnumerable<T> toIntersect, Func<T, object> keyExtractor)
        {
            return list.Intersect(toIntersect, new KeyEqualityComparer<T>(keyExtractor));
        }

        public static IOrderedEnumerable<T> OrderBy<T, TKey>(this IEnumerable<T> list, Func<T, TKey> keySelector, Func<TKey, TKey, int> comparer)
        {
            return list.OrderBy(keySelector, new DelegateComparer<TKey>(comparer));
        }

        public static IOrderedEnumerable<T> OrderByDescending<T, TKey>(this IEnumerable<T> list, Func<T, TKey> keySelector, Func<TKey, TKey, int> comparer)
        {
            return list.OrderByDescending(keySelector, new DelegateComparer<TKey>(comparer));
        }

        public static bool SequenceEqual<T>(this IEnumerable<T> list, IEnumerable<T> sequenceToEqual, Func<T, object> keyExtractor)
        {
            return list.SequenceEqual(sequenceToEqual, new KeyEqualityComparer<T>(keyExtractor));
        }

        public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, object> keyExtractor)
        {
            return first.Union(second, new KeyEqualityComparer<TSource>(keyExtractor));
        }

        public static IEnumerable<T> ToEnumerable<T>(this T o)
        {
            return new List<T>() { o };
        }

        public static bool IsNullOrEmpty(this string value)
        {
            return string.IsNullOrEmpty(value);
        }

        public static string FormatIt(this string val, params object[] args)
        {
            return string.Format(val, args);
        }

        public static bool IsSymmetric<T>(this IEnumerable<T> list, Func<T, T, bool> comparer)
        {
            var rv = false;
            var center = default(T);

            rv = IsSymmetric(list, comparer, out center);

            return rv;
        }

        public static bool IsSymmetric<T>(this IEnumerable<T> list, Func<T, T, bool> comparer, out T center)
        {
            var rv = true;
            var count = list.Count();
            var halfFst = list.Take(count / 2);
            var halfSec = list.Reverse().Take(count / 2);

            center = default(T);

            foreach (var i in halfFst)
            {
                if (!halfSec.Contains(i, comparer))
                {
                    rv = false;

                    break;
                }
            }

            if (rv)
            {
                center = list.Skip(count / 2).FirstOrDefault();
            }

            return rv;
        }
    }

    public class KeyEqualityComparer<T> : IEqualityComparer<T>
    {
        private readonly Func<T, T, bool> comparer;
        private readonly Func<T, object> keyExtractor;

        // Enable to only specify the key to compare with: y => y.CustomerID
        public KeyEqualityComparer(Func<T, object> keyExtractor) : this(keyExtractor, null) { }
        // Enable to specify how to tel if two objects are equal: (x, y) => y.CustomerID == x.CustomerID
        public KeyEqualityComparer(Func<T, T, bool> comparer) : this(null, comparer) { }

        public KeyEqualityComparer(Func<T, object> keyExtractor, Func<T, T, bool> comparer)
        {
            this.keyExtractor = keyExtractor;
            this.comparer = comparer;
        }

        public bool Equals(T x, T y)
        {
            if (comparer != null)
                return comparer(x, y);
            else
            {
                var valX = keyExtractor(x);
                if (valX is IEnumerable<object>) // The special case where we pass a list of keys
                    return ((IEnumerable<object>)valX).SequenceEqual((IEnumerable<object>)keyExtractor(y));

                return valX.Equals(keyExtractor(y));
            }
        }

        public int GetHashCode(T obj)
        {
            if (keyExtractor == null)
                return obj.ToString().ToLower().GetHashCode();
            else
            {
                var val = keyExtractor(obj);
                if (val is IEnumerable<object>) // The special case where we pass a list of keys
                    return (int)((IEnumerable<object>)val).Aggregate((x, y) => x.GetHashCode() ^ y.GetHashCode());

                return val.GetHashCode();
            }
        }
    }

    internal class DelegateComparer<T> : IComparer<T>
    {
        private readonly Func<T, T, int> _comparer;

        public DelegateComparer(Func<T, T, int> comparer)
        {
            if (comparer == null)
                throw new ArgumentNullException("comparer");
            _comparer = comparer;
        }

        public int Compare(T x, T y)
        {
            return _comparer(x, y);
        }
    }

    public class ModalWindowService
    {
        private static List<string> reasons = null;
        public static void ShowMessage(string message)
        {
            ShowMessage(message, null);
        }
        public static void ShowMessage(string message, Action<MessageBoxResult> callback)
        {
            MessageBoxResult result = MessageBox.Show(message);
            if (callback != null) callback.Invoke(result);
        }
        public static void ShowConfirmMessage(string message, Action<MessageBoxResult> callback)
        {
            ShowConfirmMessage("消息", message, callback);
        }
        public static void ShowConfirmMessage(string caption, string message, Action<MessageBoxResult> callback)
        {
            MessageBoxResult result = MessageBox.Show(message, caption, MessageBoxButton.YesNo);
            if (callback != null) callback.Invoke(result);
        }
        public static void ShowOpenFilesDialog(string ext, string filter, Action<string[]> callback)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.AddExtension = true;
            dialog.CheckPathExists = true;
            dialog.CheckFileExists = true;
            dialog.Multiselect = true;
            dialog.DefaultExt = ext; //"lab";
            dialog.Filter = filter;// "Label files (*.lab)|*.lab";
            bool? result = dialog.ShowDialog();
            if (result.HasValue && result.Value)
            {
                if (callback != null) callback.Invoke(dialog.FileNames);
            }
        }
        public static void ShowSaveFilesDialog(string filter, Action<string> callback)
        {
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.AddExtension = true;
            dialog.Filter = filter;// "Label files (*.lab)|*.lab";
            dialog.RestoreDirectory = true;
            bool? result = dialog.ShowDialog();
            if (result.HasValue && result.Value)
            {
                if (callback != null) callback.Invoke(dialog.FileName);
            }
        }
    }
}
